Object.extend(Event, {
  _domReady : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;

    if (this._timer)  clearInterval(this._timer);
    
    this._readyCallbacks.each(function(f) { f() });
    this._readyCallbacks = null;
},
  onDOMReady : function(f) {
    if (!this._readyCallbacks) {
      var domReady = this._domReady.bind(this);
      
      if (document.addEventListener)
        document.addEventListener("DOMContentLoaded", domReady, false);
        
        /*@cc_on @*/
        /*@if (@_win32)
            document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
            document.getElementById("__ie_onload").onreadystatechange = function() {
                if (this.readyState == "complete") domReady(); 
            };
        /*@end @*/
        
        if (/WebKit/i.test(navigator.userAgent)) { 
          this._timer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) domReady(); 
          }, 10);
        }
        
        Event.observe(window, 'load', domReady);
        Event._readyCallbacks =  [];
    }
    Event._readyCallbacks.push(f);
  }
});

var TweedleDo = function (options) {
	var me = this;
	Event.onDOMReady(function(){
		me.initialize();
	});
}
	
TweedleDo.prototype.initialize = function() {	
	var me = this;	 
	me.updater = new TaskUpdater();
	me.view  = new TaskView();	
	Sortable.create("workingon",
						{
							dropOnEmpty:true,
							constraint:null,
							containment:[$("workingon"),$("paused"),$("completed")],
							onChange:me.workingonUpdating.bind(me),
							onUpdate:me.workingonUpdated.bind(me)
						}
					);
	Sortable.create("paused",
						{
							dropOnEmpty:true,
							constraint:null,
							containment:[$("workingon"),$("paused"),$("completed")],
							onChange:me.pausedUpdating.bind(me),
							onUpdate:me.pausedUpdated.bind(me)
						}
					);
	Sortable.create("completed",
						{
							dropOnEmpty:true,
							constraint:null,
							containment:[$("workingon"),$("paused"),$("completed")],
							onChange:me.completedUpdating.bind(me),
							onUpdate:me.completedUpdated.bind(me)
						}
					);
					
	$$("li.task").each(function(item){
		item.observe("mouseover", function(){item.addClassName("dragging");});
		item.observe("mouseout", function(){item.removeClassName("dragging");});
	});
	
	$("addtasklink").observe("click", function(){
		me.view.toggleAddingTask();
	});
	
	$("submitaddtask").observe("click", function(event){
		me.addTask();
		Event.stop(event);
	});
	
	$("canceladdtask").observe("click", function(){
		me.view.toggleAddingTask();
		$("namerequired").hide();
	});
	//Sortable.create("peopletasks",{constraint:null,containment:[$("workingon"),$("paused"),$("people")]});
}

TweedleDo.prototype.workingonUpdating = function(el) { 
	var me = this;
	if(!me.dragging) {
		me.dragging = true;
		me.taskSrc = "workingon";
		me.view.dragNodeStart(el, me.taskSrc);
		me.currentTaskId = el.id.split("_")[1];
		//console.log("dragging workingon - taskid:%s, , tasksrc:%s, taskdest:%s", el.id, me.taskSrc);
	}	
}

TweedleDo.prototype.pausedUpdating = function(el) { 
	var me = this;
	if(!me.dragging) {
		me.dragging = true;
		me.taskSrc = "paused";
		me.view.dragNodeStart(el, me.taskSrc);
		me.currentTaskId = el.id.split("_")[1];		
		//console.log("dragging paused - taskid:%s, tasksrc:%s, taskdest:%s", el.id, me.taskSrc);
	}
}

TweedleDo.prototype.completedUpdating = function(el) { 
	var me = this;
	if(!me.dragging) {
		me.dragging = true;
		me.taskSrc = "completed";
		me.view.dragNodeStart(el, me.taskSrc);
		me.currentTaskId = el.id.split("_")[1];		
		//console.log("dragging paused - taskid:%s, tasksrc:%s, taskdest:%s", el.id, me.taskSrc);
	}
}

TweedleDo.prototype.workingonUpdated = function() {
	var me = this;
	//console.log("starting update: workingon, src=%s, id=%s", me.taskSrc, me.currentTaskId);
	if(me.taskSrc != "workingon") {
		//console.log("starting task, src=%s, id=%s", me.taskSrc, me.currentTaskId);
		me.view.taskStarted();
		me.updater.startTask(me.currentTaskId);
	}
	me.dragging = false;	
	//console.log("completed updated: workingon, taskid:%s, tasksrc:%s, taskdest:%s", me.currentTaskId, me.taskSrc);
}

TweedleDo.prototype.pausedUpdated = function(pausedList) {
	var me = this;
	//console.log("starting update, paused, src=%s, id=%s", me.taskSrc, me.currentTaskId);
	if(me.taskSrc == "workingon" || me.taskSrc == "completed") {
		//console.log("pausing task, src=%s, id=%s", me.taskSrc, me.currentTaskId);
		me.view.taskPaused();
		me.pauseTaskInProgress(pausedList);
	} else if (me.taskSrc == "completed") {
	}
	me.dragging = false;
	//console.log("completed update, paused, taskid:%s, tasksrc:%s, taskdest:%s", me.currentTaskId, me.taskSrc);
}

TweedleDo.prototype.completedUpdated = function(completedList) {
	var me = this;
	//console.log("starting update, paused, src=%s, id=%s", me.taskSrc, me.currentTaskId);
	if(me.taskSrc == "workingon" || me.taskSrc == "paused") {
		//console.log("pausing task, src=%s, id=%s", me.taskSrc, me.currentTaskId);
		me.view.taskCompleted();
		me.completeTaskInProgress(completedList);
	} else if (me.taskSrc == "paused") {
	}
	me.dragging = false;
	//console.log("completed update, paused, taskid:%s, tasksrc:%s, taskdest:%s", me.currentTaskId, me.taskSrc);
}
	
TweedleDo.prototype.startTask = function() {
	var me = this;
	me.updater.startTask(me.currentTaskId);
}

TweedleDo.prototype.pauseTaskInProgress = function(pausedList) {
	var me = this;
	var ids = Sortable.serialize(pausedList).split('&');
	var ordinal = ids.length;
	for(var i=0;i<ids.length;i++) {
		var id = ids[i].split('=')[1];
		if(id == me.currentTaskId) {
			ordinal = i+1;
			break;
		}
	}
	//console.log("task:%s, ord:%s",me.currentTaskId, ordinal);
	me.updater.pauseTask(me.currentTaskId,ordinal);
}

TweedleDo.prototype.completeTaskInProgress = function(completedList) {
	var me = this;
	var ids = Sortable.serialize(completedList).split('&');
	var ordinal = ids.length;
	for(var i=0;i<ids.length;i++) {
		var id = ids[i].split('=')[1];
		if(id == me.currentTaskId) {
			ordinal = i+1;
			break;
		}
	}
	//console.log("task:%s, ord:%s",me.currentTaskId, ordinal);
	me.updater.completeTask(me.currentTaskId);
}

TweedleDo.prototype.addTask = function() {
	var me = this;
	var taskName = $("addTask")["name"].getValue();
	if(!taskName.blank()){
		var params = $("addTask").serialize();
		var ord = me.view.taskAdded(taskName);
		params = params + "&ord=" + ord;
		me.updater.addPausedTask(params);		
		$("namerequired").hide();
	} else {
		$("namerequired").show();
	}
}			

var TaskView = function() {
	var me = this;
	me.initialize();
}
	
TaskView.prototype.initialize = function() {
	if($$("#workingon li.task").length == 0) {
		$$("#workingon li.hint")[0].show();
	}
	if($$("#paused li.task").length == 0) {
		$$("#paused li.hint")[0].show();
	}
	if($$("#completed li.task").length == 0) {
		$$("#completed li.hint")[0].show();
	}
	$("addtaskform").toggle();
} 



TaskView.prototype.dragNodeStart = function(node, src) {
	this.draggingNode = $(node);
	//console.log("%s, %s", src, this.taskContainerIsEmpty(src));
	if(this.taskContainerIsEmpty(src)){
		this.showHint(src);
	}
}

TaskView.prototype.taskContainerIsEmpty = function(id){
	var selector = "#" + id + " li.task";
	if ($$(selector).length == 1) {
		//console.log("container %s is empty", id);
	}
	return ($$(selector).length == 1);
}

TaskView.prototype.showHint = function(id) {
	var selector = "#" + id + " li.hint";
	//console.log("showing hint for %s", id);
	$$(selector)[0].show();
}

TaskView.prototype.hideHint = function(id) {
	var selector = "#" + id + " li.hint";
	//console.log("hiding hint for %s", id);
	$$(selector)[0].hide();
}

TaskView.prototype.getInProgressNode = function(){
	return $$("#workingon li.inprogress")[0];
}

TaskView.prototype.toggleAddingTask = function() {
	$("addtaskform").toggle();
}

TaskView.prototype.taskAdded = function(name) {
	var me = this;
	var newTaskNode = document.createElement("li");
	newTaskNode.innerHTML = name;
	$(newTaskNode).addClassName("task");
	$(newTaskNode).addClassName("paused");
	$("paused").appendChild(newTaskNode);
	$("addTask")["name"].clear();
	me.toggleAddingTask();
	me.hideHint("paused");
	return $$("#paused li.task").length;
}

TaskView.prototype.taskStarted = function() {
	var me = this;
	this.hideHint("workingon");		
	var node = me.getInProgressNode();
	if(node) {		
		me.bumpTaskToPaused(node);
	}	
	//console.log("marking %s in progress", this.draggingNode.id);
	this.draggingNode.removeClassName("paused");
	this.draggingNode.addClassName("inprogress");
}

TaskView.prototype.taskPaused = function() {
	var me = this;
	if(this.taskContainerIsEmpty("paused")){
		this.hideHint("paused");
	}
}

TaskView.prototype.taskCompleted = function() {
	var me = this;
	if(this.taskContainerIsEmpty("completed")){
		this.hideHint("completed");
	}
}

TaskView.prototype.bumpTaskToPaused = function(node) {
	//console.log("bumping node in progress %s",node.id)
	node.removeClassName("inprogress");
	node.addClassName("paused");
	$("paused").appendChild(node);
}

var TaskUpdater = function() {}

TaskUpdater.prototype.getWorkingOnTasks = function() {
	new Ajax.Updater('working_on_div', '/refresh_working_on/', {method:'get'});
}

TaskUpdater.prototype.getPausedTasks = function() {
	new Ajax.Updater('paused_tasks_div', '/refresh_paused_tasks/', {method:'get'});
}

TaskUpdater.prototype.addPausedTask = function(params) {
	new Ajax.Request('/create_paused_task/', {method:'post', parameters:params});
}
	
TaskUpdater.prototype.startTask = function(taskId) {
	new Ajax.Request('/start_paused_task/' + taskId + '/', {method:'get'});
}
TaskUpdater.prototype.pauseTask = function(taskId, ordinal) {
	new Ajax.Request('/pause_task/' + taskId + '/' + ordinal + '/', {method:'get'});
}
TaskUpdater.prototype.completeTask = function(taskId, ordinal) {
	new Ajax.Request('/complete_task/' + taskId + '/', {method:'get'});
}
